using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

namespace ExpeditionJourney.HotUpdate
{
    /// <summary>
    /// 资源清单类，对应服务器版本清单JSON
    /// </summary>
    [Serializable]
    public class Manifest
    {
        public string latestVersion;
        public Dictionary<string, VersionInfo> versions;
    }

    /// <summary>
    /// 版本信息类
    /// </summary>
    [Serializable]
    public class VersionInfo
    {
        public string releaseDate;
        public string description;
        public Dictionary<string, ResourceInfo> resources;
    }

    /// <summary>
    /// 资源信息类
    /// </summary>
    [Serializable]
    public class ResourceInfo
    {
        public string md5;
        public long size;
        public string url;
    }

    /// <summary>
    /// 热更新管理器
    /// </summary>
    public class HotUpdateManager : MonoBehaviour
    {
        [Header("热更新配置")]
        [SerializeField] private string serverUrl = "http://localhost:8080"; // 服务器地址
        [SerializeField] private string currentVersion = "v1.0"; // 当前版本

        [Header("调试设置")]
        [SerializeField] private bool logDebugInfo = true;

        private Manifest serverManifest;
        private Dictionary<string, ResourceInfo> needUpdateResources = new Dictionary<string, ResourceInfo>();
        private int totalUpdateCount = 0;
        private int currentUpdateCount = 0;

        // 事件
        public event Action<bool, string> OnCheckVersionComplete; // 检查版本完成事件 (是否有更新, 消息)
        public event Action<float, string> OnUpdateProgress; // 更新进度事件 (进度百分比, 当前更新资源名)
        public event Action<bool, string> OnUpdateComplete; // 更新完成事件 (是否成功, 消息)

        private void Start()
        {
            // 检查本地持久化目录是否存在
            if (!Directory.Exists(GetPersistentDataPath()))
            {
                Directory.CreateDirectory(GetPersistentDataPath());
            }

            // 这里可以添加自动检查更新的逻辑
            // CheckForUpdates();
        }

        /// <summary>
        /// 开始检查更新
        /// </summary>
        public void CheckForUpdates()
        {
            StartCoroutine(CheckVersionCoroutine());
        }

        /// <summary>
        /// 开始下载更新
        /// </summary>
        public void StartUpdate()
        {
            if (needUpdateResources.Count == 0)
            {
                if (OnUpdateComplete != null)
                    OnUpdateComplete(true, "没有需要更新的资源");
                return;
            }

            totalUpdateCount = needUpdateResources.Count;
            currentUpdateCount = 0;
            StartCoroutine(DownloadAllResources());
        }

        /// <summary>
        /// 获取本地持久化目录
        /// </summary>
        private string GetPersistentDataPath()
        {
            return Path.Combine(Application.persistentDataPath, "HotUpdateAssets");
        }

        /// <summary>
        /// 获取资源的本地路径
        /// </summary>
        public string GetLocalResourcePath(string resourceKey)
        {
            return Path.Combine(GetPersistentDataPath(), resourceKey);
        }

        /// <summary>
        /// 检查资源是否存在更新
        /// </summary>
        private IEnumerator CheckVersionCoroutine()
        {
            DebugLog("开始检查版本更新...");

            // 获取服务器版本信息
            string versionUrl = $"{serverUrl}/api/version";
            UnityWebRequest www = UnityWebRequest.Get(versionUrl);
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                DebugLog($"获取服务器版本信息失败: {www.error}");
                if (OnCheckVersionComplete != null)
                    OnCheckVersionComplete(false, $"无法连接到服务器: {www.error}");
                yield break;
            }

            try
            {
                // 解析服务器版本信息
                string json = www.downloadHandler.text;
                serverManifest = JsonUtility.FromJson<Manifest>(json);

                if (serverManifest == null || serverManifest.versions == null)
                {
                    DebugLog("服务器清单格式错误");
                    if (OnCheckVersionComplete != null)
                        OnCheckVersionComplete(false, "服务器清单格式错误");
                    yield break;
                }

                // 检查是否有新版本
                if (serverManifest.latestVersion != currentVersion)
                {
                    DebugLog($"检测到新版本: {serverManifest.latestVersion}, 当前版本: {currentVersion}");

                    // 检查哪些资源需要更新
                    needUpdateResources.Clear();
                    VersionInfo latestVersionInfo = serverManifest.versions[serverManifest.latestVersion];

                    foreach (var resourceItem in latestVersionInfo.resources)
                    {
                        string resourceKey = resourceItem.Key;
                        ResourceInfo resourceInfo = resourceItem.Value;
                        string localPath = GetLocalResourcePath(resourceKey);

                        // 如果本地文件不存在或MD5不匹配，则需要更新
                        bool needUpdate = !File.Exists(localPath);
                        if (!needUpdate)
                        {
                            string localMd5 = CalculateMD5(localPath);
                            needUpdate = localMd5 != resourceInfo.md5;
                        }

                        if (needUpdate)
                        {
                            needUpdateResources.Add(resourceKey, resourceInfo);
                        }
                    }

                    if (needUpdateResources.Count > 0)
                    {
                        DebugLog($"需要更新 {needUpdateResources.Count} 个资源");
                        if (OnCheckVersionComplete != null)
                            OnCheckVersionComplete(true, $"有可用更新: 从 {currentVersion} 更新到 {serverManifest.latestVersion}，共 {needUpdateResources.Count} 个资源");
                    }
                    else
                    {
                        DebugLog("所有资源已是最新");
                        if (OnCheckVersionComplete != null)
                            OnCheckVersionComplete(false, "所有资源已是最新");
                    }
                }
                else
                {
                    DebugLog("当前已是最新版本");
                    if (OnCheckVersionComplete != null)
                        OnCheckVersionComplete(false, "当前已是最新版本");
                }
            }
            catch (Exception ex)
            {
                DebugLog($"解析版本信息时出错: {ex.Message}");
                if (OnCheckVersionComplete != null)
                    OnCheckVersionComplete(false, $"解析版本信息时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 下载所有需要更新的资源
        /// </summary>
        private IEnumerator DownloadAllResources()
        {
            bool allSuccess = true;
            StringBuilder errorMessages = new StringBuilder();

            foreach (var kvp in needUpdateResources)
            {
                string resourceKey = kvp.Key;
                ResourceInfo resourceInfo = kvp.Value;

                bool success = false;
                yield return StartCoroutine(DownloadResource(resourceKey, resourceInfo, (result) => success = result));

                if (!success)
                {
                    allSuccess = false;
                    errorMessages.AppendLine($"资源 {resourceKey} 下载失败");
                }

                currentUpdateCount++;
                float progress = (float)currentUpdateCount / totalUpdateCount;
                if (OnUpdateProgress != null)
                    OnUpdateProgress(progress, resourceKey);
            }

            // 如果所有资源都成功下载，则更新当前版本
            if (allSuccess)
            {
                currentVersion = serverManifest.latestVersion;
                PlayerPrefs.SetString("CurrentVersion", currentVersion);
                PlayerPrefs.Save();
                
                DebugLog($"所有资源更新成功，当前版本: {currentVersion}");
                if (OnUpdateComplete != null)
                    OnUpdateComplete(true, "所有资源更新成功");
            }
            else
            {
                DebugLog($"某些资源更新失败:\n{errorMessages}");
                if (OnUpdateComplete != null)
                    OnUpdateComplete(false, $"某些资源更新失败: {errorMessages}");
            }
        }

        /// <summary>
        /// 下载单个资源
        /// </summary>
        private IEnumerator DownloadResource(string resourceKey, ResourceInfo resourceInfo, Action<bool> callback)
        {
            string resourceUrl = $"{serverUrl}{resourceInfo.url}";
            DebugLog($"开始下载: {resourceKey} 从 {resourceUrl}");

            UnityWebRequest www = UnityWebRequest.Get(resourceUrl);
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                DebugLog($"下载失败: {resourceKey}, 错误: {www.error}");
                callback(false);
                yield break;
            }

            try
            {
                // 确保目录存在
                string localPath = GetLocalResourcePath(resourceKey);
                string directory = Path.GetDirectoryName(localPath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // 保存文件
                File.WriteAllBytes(localPath, www.downloadHandler.data);

                // 验证MD5
                string downloadedMd5 = CalculateMD5(localPath);
                if (downloadedMd5 != resourceInfo.md5)
                {
                    DebugLog($"MD5校验失败: {resourceKey}, 期望: {resourceInfo.md5}, 实际: {downloadedMd5}");
                    callback(false);
                    yield break;
                }

                DebugLog($"下载成功: {resourceKey}");
                callback(true);
            }
            catch (Exception ex)
            {
                DebugLog($"保存文件时出错: {resourceKey}, 错误: {ex.Message}");
                callback(false);
            }
        }

        /// <summary>
        /// 计算文件的MD5值
        /// </summary>
        private string CalculateMD5(string filePath)
        {
            using (var md5 = MD5.Create())
            {
                using (var stream = File.OpenRead(filePath))
                {
                    byte[] hash = md5.ComputeHash(stream);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < hash.Length; i++)
                    {
                        sb.Append(hash[i].ToString("x2"));
                    }
                    return sb.ToString();
                }
            }
        }

        /// <summary>
        /// 从本地加载AssetBundle
        /// </summary>
        public AssetBundle LoadAssetBundleFromLocal(string resourceKey)
        {
            string localPath = GetLocalResourcePath(resourceKey);
            if (!File.Exists(localPath))
            {
                DebugLog($"本地资源不存在: {resourceKey}");
                return null;
            }

            try
            {
                return AssetBundle.LoadFromFile(localPath);
            }
            catch (Exception ex)
            {
                DebugLog($"加载本地AssetBundle失败: {resourceKey}, 错误: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 调试日志
        /// </summary>
        private void DebugLog(string message)
        {
            if (logDebugInfo)
            {
                Debug.Log($"[HotUpdate] {message}");
            }
        }
    }
} 